package javaNIO1.Selectors;

import java.io.IOException;
import java.net.InetSocketAddress;
import java.net.ServerSocket;
import java.net.Socket;
import java.nio.ByteBuffer;
import java.nio.channels.*;
import java.util.Iterator;

/**
 * Created with Intel IDEA.
 *
 * @Auther: gjt
 * @Date: 2024/7/27 13:27
 */
public class UseSelector {
    private final static int PORT = 13;

    public static void main(String[] args) throws IOException {
//        UseSelector.go(args);
    }

    
     void go(String[] args) {
        int port = PORT;
        if (args != null && args.length > 0) {
            port = Integer.parseInt(args[0]);
        }

        System.out.println("正在监听的端口是: " + port);

        try {
            ServerSocketChannel serverSocketChannel = ServerSocketChannel.open();
            if (!serverSocketChannel.isOpen()) return;
            serverSocketChannel.configureBlocking(false);

            ServerSocket serverSocket = serverSocketChannel.socket();
            serverSocket.bind(new InetSocketAddress(port));
            Selector selector = Selector.open();
            if (!selector.isOpen()) return;

            selector.select();
            serverSocketChannel.register(selector, SelectionKey.OP_READ);

            while (true) {
                int select = selector.select();
                if (select == 0) continue;

                Iterator<SelectionKey> iterator = selector.selectedKeys().iterator();
                while (iterator.hasNext()) {
                    SelectionKey key = iterator.next();

                    if (key.isAcceptable()) {
                        ServerSocketChannel channel = (ServerSocketChannel) key.channel();
                        SocketChannel accept = channel.accept();
                        registerChannel(selector, accept, SelectionKey.OP_READ);
                        sayHello(accept);
                    }

                    if (key.isReadable()) {
                        readDataFromSocket(key);
                    }
                    iterator.remove();
                }
            }

        } catch (IOException e) {
            throw new RuntimeException(e);
        }
    }


    protected  void registerChannel(Selector selector, SelectableChannel selectableChannel, int ops) throws IOException {
        if (selectableChannel == null) return;
        selectableChannel.configureBlocking(false);
        selectableChannel.register(selector, ops);
    }


    protected  void readDataFromSocket(SelectionKey key) throws IOException {
        if(!key.isValid())return;

        SocketChannel channel = (SocketChannel) key.channel();
        int count;
        buffer.clear();

        while ((count = channel.read(buffer)) > 0) {
            buffer.flip();
            while (buffer.hasRemaining()) {
                channel.write(buffer);
            }
            buffer.clear();
        }

        if (count < 0) {
            channel.close();
        }
    }

    private  ByteBuffer buffer = ByteBuffer.allocateDirect(1024);

    protected  void sayHello(SocketChannel socketChannel) throws IOException {
        buffer.clear();
        buffer.put("Hi there".getBytes());
        socketChannel.write(buffer);
    }

}
